/**
 * 
 * @brief  bsp_msgqueue.c
 * @param  None
 * 
 * @author mmv
 * @date   2025/4/10
 * 
 */
/* include */
#include "bsp_msgqueue.h"

/* define */

/* typedef */

/* global varibles */
message_queue g_track_info_queue = {
    .max_size = MSG_QUEUE_SIZE,
};

message_queue g_dsp_info_queue = {
    .max_size = MSG_QUEUE_SIZE,
};


/* private function */

/* function */
/*****************************************************************************/
/**
*
* queue_init    消息队列初始化
*
* @param	queue -- 队列变量指针
*
* @return	返回结果，0：成功；1：失败
*
* @note		None.
*
******************************************************************************/
uint32_t queue_init(message_queue *queue) 
{
    // 初始化锁
    if (pthread_mutex_init(&queue->mutex, NULL) != 0) 
    {
        perror("mutex_init failed");
        return 1;
    }

    // 初始化条件变量
    if ((pthread_cond_init(&queue->cond_not_empty, NULL) != 0) || (pthread_cond_init(&queue->cond_not_full, NULL) != 0)) 
    {
        perror("cond_init failed");
        return 1;
    }

    // 初始化头、尾、数量
    queue->head = NULL;
    queue->tail = NULL;
    queue->count = 0;
    
    return 0;
}


/*****************************************************************************/
/**
*
* queue_destrpy    销毁消息队列
*
* @param	queue -- 队列变量指针
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
void queue_destroy(message_queue *queue) 
{
    // 销毁队列数据，释放数据占用内存
    pthread_mutex_lock(&queue->mutex);
    message_node *node = queue->head;
    while (node) 
    {
        message_node *temp = node;
        node = node->next;
        free(temp);
    }
    pthread_mutex_unlock(&queue->mutex);

    // 销毁锁
    pthread_mutex_destroy(&queue->mutex);

    // 销毁条件变量
    pthread_cond_destroy(&queue->cond_not_empty);
    pthread_cond_destroy(&queue->cond_not_full);

    return;
}


/*****************************************************************************/
/**
*
* add_to_queue  添加消息到消息队列，消息队列满时，数据丢弃
*
* @param	p_track_info-- 即将上传的目标信息表地址
*           queue       -- 队列变量指针
*
* @return	返回结果，0：成功；1：失败
*
* @note		None.
*
******************************************************************************/
uint32_t add_to_queue(const void *p_msg_info, uint32_t len, message_queue *queue) 
{

    pthread_mutex_lock(&queue->mutex);
    // 等待队列有可用空间，
    while (queue->count >= queue->max_size) 
    {
        printf("queue msg count reach max, data give up...\n");
        // 唤醒处理线程，处理消息队列中的数据
        pthread_cond_signal(&queue->cond_not_empty);
        pthread_mutex_unlock(&queue->mutex);
        return 1;
        // pthread_cond_wait(&queue->cond_not_full, &queue->mutex);
    }

    message_node *node = malloc(sizeof(message_node));
    if (!node) 
    {
        printf("add_to_queue malloc failed.\n");
        pthread_mutex_unlock(&queue->mutex);
        return 1;
    }

    memcpy((void *)&node->data, p_msg_info, len);
    node->next = NULL;

    if (queue->tail)       // 列表不为空
    {
        queue->tail->next = node;
    } 
    else                    // 列表为空
    {
        queue->head = node;
    }
    queue->tail = node;

    // 消息数量加1
    queue->count++;

    // 唤醒处理线程，处理消息队列中的数据
    pthread_cond_signal(&queue->cond_not_empty);
    pthread_mutex_unlock(&queue->mutex);

    return 0;
}


/*****************************************************************************/
/**
*
* take_out_from_queue   从消息队列中取出数据（无数据时阻塞）
*
* @param	queue -- 队列变量指针
*
* @return	返回结果，data：即将上传的目标信息表地址；NULL：失败
*
* @note		None.
*
******************************************************************************/
message_node *take_out_from_queue(message_queue *queue)
{
    pthread_mutex_lock(&queue->mutex);

    // 等待队列有数据
    while (queue->count == 0) 
    {
        pthread_cond_wait(&queue->cond_not_empty, &queue->mutex);
    }

    // 按照从前到后的顺序取数据
    message_node *node = queue->head;

    // 在链表中删掉已取出的数据
    queue->head = node->next;
    if (!queue->head)      // 取出数据后，链表成空的话，那么头尾皆赋值为空
    {
        queue->tail = NULL;
    }

    // 链表中消息数量减1
    queue->count--;

    // pthread_cond_signal(&queue->cond_not_full);
    pthread_mutex_unlock(&queue->mutex);

    return node;
}